import java.io.*;
import java.util.Scanner;

public class IO {
    //文件操作   字节流和字符流
    //字节流
       //             InputStream和       OutputStream 他们两个都是抽象类,不能实例化
       //实例化        FileInputstream     FileOutputStream
                   //构造方法填写参数:绝对路径,相对路径,或者是File对象
    //字符流
       // Read 和Writer
    public static void main(String[] args) throws IOException {  //文件没找到抛出的异常,也是IOException的子类,写成这个也可以
        InputStream inputStream = new FileInputStream("d:/test.text");
        inputStream.read();  //无参数,一次读取一个字节 ,返回值是一个int,读到的数据就是0~255,正好是1byte
                             //返回int为了能够额外的余地表示"到达末尾"  -1 这种情况.确保读到的数据都是整数:对于字节这样的数据不是直接进行
                            //算数运算的,如果是算数运算,就需要符号.
        inputStream.read(new byte[1024]);   //这种写法在Java中不常见,C++比较典型.用参数来作为函数的返回结果,"输出型参数"
        //Java中更常见的是,用参数表示"输入",用返回值表述"输出",这句代码就是方法执行完毕后,就会把读到的数据填充到byte数组中,
        // 返回值是int表示实际读取了多少字节,一次读多少取决于数组长度,如果不够,能填多少是多少
        //英文字母都是asci码表上的
        //在Windows下:回车是让光标回到行首(不会新增一行),换行才是新增一行

        inputStream.read(new byte[1024],0,90);  //这个方法和上面一个很像,就是不是填充完,而是填充一部分.

        //关闭文件
        //为什么要关闭文件?   ---->打开开一个文件的时候,会在操作系统内核,PCB结构体中,给"文件描述符表"田间一个元素,这个元素是表示,
        // 当前打开文件的相关信息,当执行close的时候,就会释放这个文件描述符表上对应的元素.如果一直打开,不关闭,文件描述符表满了,就会打开失败.
        //称为文件资源泄露,多个线程共用一个文件描述符表
        //系统api,可以获得到当前进程已经打开了,多少文件,用于报警.文件描述附表的大小是可控的,可以配置.
        //当把流对象写到try括号后面的时候,,会自动调用close这个方法.,当然只有实现Closeable这个接口才能这么写.
        try(InputStream inputStream1=new FileInputStream("d:/test.text")){
            byte[] bytes=new byte[1024];
            int n=inputStream1.read(bytes);
            for (int i = 0; i < n; i++) {
                System.out.println(bytes[i]);
            }

        }


        //OutputStream
        try(OutputStream outputStream=new FileOutputStream("d:/test.text",true)){
            outputStream.write(97);//这个和write一样有三个版本,几乎一样,但是没有返回值,同时会将原有的文件内容清空,不是write清空的,而是
            //打开清空的.如果使用追加写不会清空.在构造方法里面加上true
            outputStream.write(98);
            outputStream.write(99);
            outputStream.write(99);
        }



        //-------------------------------------------------------------------------
        //Read,Writer
        //在Java中,在调用一些方法的时候会进行转码,就比如说Read里面的read这个方法,它是一次读取连个字节,但是在utf-8中,一个汉字使用三个字节表示的
        //但是char大小是两个字节,所以Java会转换编码方式,将utf-8,转为unicode,在unicode中汉字占两个字节,同样,String里面的charAt,这个方法也是
        //进行了转码,注意这是汉字情况下,如果是字母,就不会进行转码.
        try(Reader reader=new FileReader("d:/test.txt")){
            while(true){
                int c=reader.read();
                if(c==-1){
                    break;
                }
                char h=(char)c;
                System.out.println(c);
            }
        }
        //---------------------------------------------------------------------------
        //Scanner
        //Scanner scanner=new Scanner(System.in);   //public static final InputStream in = null;
        try(InputStream inputStream1=new FileInputStream("d:/test.txt")){
            Scanner scanner=new Scanner(inputStream);
            scanner.next();

        }

    }
}
